#![no_main]
#![no_std]

use ch32v203_hal::{
    delay::Delay,
    gpio::GpioExt,
    i2c::{I2c, I2cMode},
    prelude::*,
    rcc::{PllClkSrc, RccExt},
    serial::{Serial, SerialWriter},
};
use panic_halt as _;
use riscv as _;
use riscv_rt::entry;

use ch32v2::ch32v20x as pac;
use ssd1306::{
    prelude::DisplayConfig, rotation::DisplayRotation, size::DisplaySize128x64,
    I2CDisplayInterface, Ssd1306,
};
 
#[entry]
fn main() -> ! {
    let peripherals = pac::Peripherals::take().unwrap();
    let rcc = peripherals.RCC.constrain();

    //let clocks = rcc.cfgr.freeze();
    let clocks = rcc
        .cfgr
        .use_pll((48).mhz(), PllClkSrc::Hsi)
        .hclk((8).mhz())
        .freeze();

    let gpioa = peripherals.GPIOA.split();
    let pa9 = gpioa.pa9.into_multiplex_push_pull_output();
    let pa10 = gpioa.pa10.into_floating_input();

    let usart = Serial::usart1(peripherals.USART1, (pa9, pa10), (115200).bps(), &clocks);
    let (tx, _) = usart.split();
    let mut log = SerialWriter::new(tx);

    let gpiob = peripherals.GPIOB.split();
    // LED
    //let mut led1 = gpiob.pb2.into_push_pull_output();
    // let mut led2 = gpiob.pb15.into_push_pull_output();

    //  I2C1
    let pb6 = gpiob.pb6.into_multiplex_open_drain_output();
    let pb7 = gpiob.pb7.into_multiplex_open_drain_output();
    //let pb8 = gpiob.pb8.into_multiplex_open_drain_output();
    //let pb9 = gpiob.pb9.into_multiplex_open_drain_output();

    // required peripherals.I2C1 to occupy
    let i2c = I2c::i2c1(peripherals.I2C1, (pb6, pb7), I2cMode::Standard, &clocks);

    let mut delay = Delay::new(&clocks);

    let mut display = Ssd1306::new(
        I2CDisplayInterface::new(i2c),
        DisplaySize128x64,
        DisplayRotation::Rotate0,
    )
    .into_buffered_graphics_mode();
    display.init().unwrap();

    loop {
         delay.delay_ms(1000);
        display.draw(&[12 as u8]);
    }

    // let peripherals = pac::Peripherals::take().unwrap();
    // let rcc = peripherals.RCC;

    // rcc.apb2pcenr.modify(|_, w| w.iopben().set_bit());

    // let gpiob = peripherals.GPIOB;
    // unsafe {
    //     gpiob
    //         .cfghr
    //         .modify(|_, w| w.cnf10().bits(0b00).mode10().bits(0b11))
    // };
    // // HSI 8MHz
    // // 4 opcodes to do a nop sleep here
    // let cycle = 10_000_000 / 6;
    // loop {
    //     gpiob.outdr.modify(|_, w| w.odr10().set_bit());
    //     for _ in 0..cycle {
    //         unsafe {
    //             riscv::asm::nop();
    //         }
    //     }
    //     gpiob.outdr.modify(|_, w| w.odr10().clear_bit());
    //     for _ in 0..cycle {
    //         unsafe {
    //             riscv::asm::nop();
    //         }
    //     }
    // }
}
